package arcane.object.game.sprite;

import java.awt.image.BufferedImage;

import arcane.object.ImagePath;
import arcane.object.game.map.LinkedMap;
import arcane.object.game.spell.Spell;

import com.golden.gamedev.object.sprite.AdvanceSprite;

/**
 * Extension for any Arcane sprite. Contains a collection of attributes standard
 * in most RPG games.
 * 
 * @author William Morrison
 * 
 */
public class Actor extends AdvanceSprite {
	/**
	 * Actor's base image. Equipment is rendered in layers over this template.
	 */
	protected ImagePath template;

	LinkedMap tileBG;

	private static final int ROWS = 4;
	private static final int COLUMNS = 3;

	protected int dir;
	protected int previousDir;
	protected int tileX, oldTX;
	protected int tileY, oldTY;

	protected int mana;
	protected int health;
	protected int maxHealth;
	protected int maxMana;

	protected int def;
	protected int magDef;
	protected int atk;
	protected int magAtk;
	protected int speed;
	protected int castSpeed;

	public Actor() {
		this(null, "", null);
	}

	public Actor(BufferedImage img, String path, LinkedMap map) {
		template = new ImagePath(img, path);
		this.tileBG = map;
	}

	public BufferedImage getImageTemplate() {
		return template.getImage();
	}

	public void setDefense(int def) {
		this.def = def;
	}

	public int getDefense() {
		return def;
	}

	public void setMagicDefense(int magDef) {
		this.magDef = magDef;
	}

	public int getMagicDefense() {
		return magDef;
	}

	public void setAttack(int atk) {
		this.atk = atk;
	}

	public int getAttack() {
		return atk;
	}

	public void setMagicAttack(int magAtk) {
		this.magAtk = magAtk;
	}

	public int getMagicAttack() {
		return magAtk;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public int getSpeed() {
		return speed;
	}

	public void setCastSpeed(int cast) {
		castSpeed = cast;
	}

	public int getCastSpeed() {
		return castSpeed;
	}

	public boolean isAlive() {
		return health > 0;
	}

	public boolean castSpell(Spell s) {
		if (s.getManaCost() <= mana && s.getHealthCost() < health) {
			return true;
		} else
			return false;
	}

	protected void fireSpellCastEvent() {
	}

	/**
	 * Moves this Actor by a horizontal distance dx, and a vertical distance dy.
	 * The direction is necessary for checking to see if the tile this Actor is
	 * moving to is passable or not.
	 * 
	 * Returns whether any change to the actor's position has occurred.
	 * 
	 * @param dx
	 *            horizontal increment
	 * @param dy
	 *            vertical increment
	 * @param dir
	 *            direction actor is moving in
	 * @return whether actor moved any distance
	 */
	public boolean move(int dx, int dy, int dir, long elapsedTime) {
		moveX(speed * dx * elapsedTime);
		moveY(speed * dy * elapsedTime);
		// calculate tileX and tileY
		int tempX = (int) getX() / tileBG.getTileWidth();
		int tempY = (int) getY() / tileBG.getTileWidth();
		// Determine if there's been a change in tile.
		if (tempX != tileX || tempY != tileY) {
			// has been change, check to see if can walk here
			if (tileBG.isPassable(tempX, tempY, dir)) {
				oldTX = tileX;
				oldTY = tileY;
				tileX = tempX;
				tileY = tempY;
				return true;
			}
			// No walking here from this direction
			else {
				move(-dx, -dy);
				return false;
			}
		}
		// No change in tile. We assume the tile player is on is passable
		else {
			return true;
		}
	}
}